//2021全国大学生电子设计大赛A题
//Author:Jensen_Lin 2021-11-11
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
/* Standard Includes */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "usart_user.h"
#include "stdio.h"
#include <OLED12864.H>
//FFT相关函数
#include "stm32_dsp.h"
#include "table_fft.h"
//////////////////////
#include "math.h"
#define TIMER_A_FREQ 1000000
#define TIMER_A_PERIOD 48000000 / (TIMER_A_FREQ)
//!设置采样数值
#define N 1024
/* Timer_A Continuous Mode Configuration Parameter */
const Timer_A_UpModeConfig upModeConfig = {
	//Timer can not use ACLK if in high freq
	TIMER_A_CLOCKSOURCE_SMCLK,			 // SMCLK Clock Source
	TIMER_A_CLOCKSOURCE_DIVIDER_1,		 // SMCLK/1 = 48Mhz
	TIMER_A_PERIOD - 1,					 // 1M freq
	TIMER_A_TAIE_INTERRUPT_DISABLE,		 // Disable Timer ISR
	TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE, // Disable CCR0
	TIMER_A_DO_CLEAR					 // Clear Counter
};
/* Timer_A Compare Configuration Parameter */
const Timer_A_CompareModeConfig compareConfig = {
	TIMER_A_CAPTURECOMPARE_REGISTER_1,		  // Use CCR1
	TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE, // Disable CCR interrupt
	TIMER_A_OUTPUTMODE_SET_RESET,			  // Toggle output but
	TIMER_A_PERIOD / 4 - 1					  //  Period
};

//--------------------所用的全局变量-----------------------//
//!设置数据接收完成标记位
uint8_t recv_done_flag;
uint8_t controlTable[1024];
uint16_t adc_result_array[1024];
uint16_t adc_result_data[1024];
char buffer_usart[32];		   //!用于数组调试
uint16_t adc_sample_MAX;	   //!每一次采样的最大值
uint16_t adc_offset_value = 0; //!ADC采样的偏移量
uint16_t return_data;		   //!ADC采样的最大值对应的坐标
/* DMA Control Table */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN(controlTable, 1024)
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 1024
#elif defined(__GNUC__)
__attribute__((aligned(1024)))
#elif defined(__CC_ARM)
__ALIGNED(1024)
#endif

/**
 * @brief ADC_DMA_Init
*/
void ADC_DMA_Init(void)
{
	/* Configuring DMA module */
	DMA_enableModule();
	DMA_setControlBase(controlTable);
	DMA_assignChannel(DMA_CH7_ADC14);
	DMA_setChannelControl(DMA_CH7_ADC14 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
	DMA_setChannelTransfer(DMA_CH7_ADC14 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)&ADC14->MEM[0], (void *)adc_result_array, 1024);
	DMA_assignInterrupt(INT_DMA_INT1, 7);
	DMA_clearInterruptFlag(DMA_CH7_ADC14 & 0x0F);
	Interrupt_enableInterrupt(INT_DMA_INT1);
	DMA_enableInterrupt(INT_DMA_INT1);
	DMA_enableChannel(7);
}
/**
 * @brief ADC_Sample_Single
*/
void ADC_Sample_Single(void)
{
	//![Simple CS Config]
	/* Configuring pins for peripheral/crystal usage and LED for output */
	GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION);
	GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); //!设置指示灯LED
	/* Configuring pins for peripheral/crystal usage and LED for output */
	GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
	/* Just in case the user wants to use the getACLK, getMCLK, etc. functions,
     * let's set the clock frequency in the code. */
	CS_setExternalClockSourceFrequency(32000, 48000000);
	/* Starting HFXT in non-bypass mode without a timeout. Before we start
     * we have to change VCORE to 1 to support the 48MHz frequency */
	PCM_setCoreVoltageLevel(PCM_VCORE1);
	FlashCtl_setWaitState(FLASH_BANK0, 1);
	FlashCtl_setWaitState(FLASH_BANK1, 1);
	/* Starting LFXT in non-bypass mode without a timeout. */
	CS_startLFXT(CS_LFXT_DRIVE3);
	CS_startHFXT(false);
	/* Initializing ACLK to LFXT (effectively 32khz) */
	CS_initClockSignal(CS_ACLK, CS_LFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
	/* Initializing MCLK and SMCLK to HFXT (effectively 48MHz) */
	CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
	CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
	//!初始化ADC_DMA采样
	ADC_DMA_Init();
	//![Single Sample Mode Configure]
	/* Initializing ADC (MCLK/1/4) */
	ADC14_enableModule();
	ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0);
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5, GPIO_PRIMARY_MODULE_FUNCTION);
	//ADC寄存器
	ADC14_configureSingleSampleMode(ADC_MEM0, true);
	ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A0, ADC_NONDIFFERENTIAL_INPUTS);
	//配置定时器
	Timer_A_configureUpMode(TIMER_A0_BASE, &upModeConfig);
	Timer_A_initCompare(TIMER_A0_BASE, &compareConfig);
	ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false);
	//使能转换
	ADC14_enableConversion();
	//使能通道0的中断
	ADC14_enableInterrupt(ADC_INT0);
	Interrupt_enableInterrupt(INT_ADC14);
	Interrupt_enableMaster();
	//启用定时器
	Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);
}

/**
 * @brief ADC14_IRQHandler中断
*/
void ADC14_IRQHandler(void)
{
	uint64_t status;
	status = ADC14_getEnabledInterruptStatus();
	ADC14_clearInterruptFlag(status);
	if (status & ADC_INT0)
	{
	}
}
/**
 * @brief DMA_INT1_IRQHandler中断
*/
void DMA_INT1_IRQHandler(void)
{
	Timer_A_stopTimer(TIMER_A0_BASE);
	DMA_clearInterruptFlag(0);
	/* Disable the interrupt to allow execution */
	Interrupt_disableInterrupt(INT_DMA_INT1);
	DMA_disableInterrupt(INT_DMA_INT1);
	//DMA will auto disable channel if complete
	//DMA_disableChannel(7);
	/* Disable the interrupt to allow execution */
	//Interrupt_disableInterrupt(INT_DMA_INT1);
	//DMA_disableInterrupt(INT_DMA_INT1);
	recv_done_flag = 1;
}
/*---------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------*/
/**
 * @brief 采样取最大值
*/
uint16_t Sample_Max(uint16_t *buf, uint16_t length)
{
	uint16_t i = 0;
	adc_sample_MAX = buf[0];
	for (i = 0; i < length; i++)
	{
		if (buf[i] > adc_sample_MAX)
		{
			adc_sample_MAX = buf[i];
			return_data = i;
		}
	}
	return adc_sample_MAX;
	//return return_data;
}
/**
 * @brief ADC采样归一化
*/
void normalization_adc(uint16_t *buf, uint16_t length)
{
	int i;
	for (i = 0; i < length; ++i)
	{
		buf[i] = 63 - ((buf[i] - 0) / (adc_sample_MAX - 0) * 63);
		//printf("buf0:%d\n", buf[i]);
	}
	//!显示屏画波形
	/*
	for (i = 1; i <= 128; ++i)
	{
		if (i == 1)
		{
			LCD_DrawLine(i - 1, buf[i - 1], i - 1, buf[i - 1]);
		}
		else if (i > 1)
		{
			LCD_DrawLine(i - 1, buf[(i - 1) * 8], i, buf[(i - 1) * 8]);
		}
	}*/
	for (i = 1; i <= 8; ++i)
	{
		if (i == 1)
		{
			LCD_DrawLine(i - 1, buf[i - 1], i - 1, buf[i - 1]);
		}
		if (i > 1)
		{
			LCD_DrawLine((i - 2) * 16, buf[(i - 2) * 16 * 8], (i - 1) * 16, buf[(i - 1) * 16 * 8]);
		}
	}
}

/**
 * @brief 主函数
*/
uint8_t test_flag = 0;
int main(void)
{
	recv_done_flag = 0;
	////////////////////////
	int i = 0;
	/* Halting WDT */
	WDT_A_holdTimer();
	ADC_Sample_Single();
	Usart_User_Init();
	LCD_Init(); //显示屏初始化
	//串口设置为115200
	while (1)
	{
		if (recv_done_flag == 1)
		{
			//!数值采集完成
			Interrupt_disableInterrupt(INT_ADC14);
			DMA_disableModule();
			/* 1024 data is ready, wait for next 1024 data */
			test_flag = 1;
			recv_done_flag = 0;
			GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
			//UART_transmitData(EUSCI_A0_BASE, 1 & 0xff);
			//printf("ok");
			//!重新一轮采集
			//------------------------------
			//Interrupt_enableInterrupt(INT_ADC14);
			//ADC_Sample_Single();
			//-----------------------------
		}
		if (test_flag == 1)
		{
			for (i = 0; i < N; ++i)
			{
				//UART_transmitData(EUSCI_A0_BASE, adc_result_array[i]);
				sprintf(buffer_usart, "adc1:%d\n", adc_result_array[i]);
				printf(buffer_usart);
				adc_result_data[i] = adc_result_array[i];
			}
			Sample_Max(adc_result_data, 1024);
			//printf("adc_max:%d\n", Sample_Max(adc_result_data, 1024));
			//test_flag = 2;
			//normalization_adc(adc_result_data, 1024);
			//LCD_DrawLine(0, 0, 30, 30);
			//LCD_DrawLine(30, 30, 60, 40);
		}
	}
}
